package framework.classification.entities;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import framework.AnnuaireCocola;
import framework.classification.entities.lattice.TreillisI;
import framework.classification.library.AbstractClassfication;
import framework.entity.ACLComponent;
import framework.entity.ACLEntity;
import framework.entity.ACLFunction;
import framework.entity.ACLInterface;

public class ClComponent extends ClAbstractEntity {


	public static String COMPONENT = "Component";

	private ArrayList<ACLComponent> components;
	private HashMap<String,ArrayList<String>> compoNoInter;

	public ClComponent(String s, AbstractClassfication cl, TreillisI t,
			ArrayList<ACLComponent> a) {
		super(s, cl, t);

		components = a;
		createTableModel();
		int x = this.getAttribut().size();
		int y = this.getEntity().size();
		table = new int[x][y];
		calculPair();

	}

	public void calculPair() {

		for (int x = 0; x < getAttribut().size(); x++) {
			for (int y = 0; y < getEntity().size(); y++) {
				if (isPair(getAttribut().get(x), getEntity().get(y), y))
					table[x][y] = 1;
			}

		}

	}

	public void createTableModel() {
		//liste comportant toutes les Interfaces de top niveau des differentes classifications;
		ArrayList<String> topInters = new ArrayList<String>();
		compoNoInter = new HashMap<String, ArrayList<String>>();

		//on ajoute les composants dans les colonnes
		for (ACLComponent aclcomp : components){
			getEntity().add(aclcomp.getName());

			//----------------------- Interface Provided
			//on ajoutes les interfaces fournis des differents composants
			for (ACLInterface aclInterpro : aclcomp.getInterfacesPro()){
				//on recupere la classification de l'interface
				//et on y ajoute toutes les interfaces comrises
				ClInterfaceProvided clpro =getAbstractClassfication().getInterfacesProvided().get(aclInterpro.getName());
				for (String interpro : clpro.getRealReduced().keySet()){
					ACLInterface aclinter = new ACLInterface(interpro,ACLFunction.MODE2);

					if (!getAttribut().contains("Pro="+aclinter.getName()))
						getAttribut().add("Pro="+aclinter.getName());
				}
				for (String interpro : clpro.getAbstractReduced().keySet()){
					ACLInterface aclinter = new ACLInterface(interpro,ACLFunction.MODE2);

					if (!getAttribut().contains("Pro="+aclinter.getName()))
						getAttribut().add("Pro="+aclinter.getName());
				}
			}

			//--------------------------- Interface Required						
			//on ajoute les interfaces requises des different composants
			for (ACLInterface aclIntereq : aclcomp.getInterfacesReq()){

				//on recupere la classification de l'interface
				//et on y ajoute toutes les interfaces comprises dans le composant
				ClInterfaceRequired clreq = getAbstractClassfication().getInterfacesRequired().get(aclIntereq.getName());

				//on sauvegarde le top de la classification
				if (!topInters.contains(clreq.getLattice().getMaxSuperEntity())){
					ACLInterface aclnointer = new ACLInterface(clreq.getLattice().getMaxSuperEntity(),ACLFunction.MODE2);
					topInters.add(aclnointer.getName());
				}

				for (String interreq : clreq.getRealReduced().keySet()){
					ACLInterface aclinter = new ACLInterface(interreq,ACLFunction.MODE2);

					if (!getAttribut().contains("Req="+aclinter.getName()))
						getAttribut().add("Req="+aclinter.getName());
				}
				for (String interreq : clreq.getAbstractReduced().keySet()){
					ACLInterface aclinter = new ACLInterface(interreq,ACLFunction.MODE2);

					if (!getAttribut().contains("Req="+aclinter.getName()))
						getAttribut().add("Req="+aclinter.getName());
				}
			}
		}
		//on verifie que les composants possedent tous les types d'interfaces requises
		//sinon on rajoute la negation de l'interface
		//on sauvegarde le couple composant interface 
		//(le composant ne possede pas cette interface ou une interface appartenant  la classification de l'interface)
		for (ACLComponent component : components){

			for (String intertop : topInters){
				Boolean add = true;
				for (ACLInterface aclinter : component.getInterfacesReq()){
					ClInterfaceRequired clinterreq = cl.getInterfacesRequired().get(aclinter.getName());
					ACLInterface aclinterReqMax =new ACLInterface(clinterreq.getLattice().getMaxSuperEntity(),ACLFunction.MODE2);
					if (intertop.equals(aclinterReqMax.getName()))
						add = false;

				}

				if (add){

					if (!compoNoInter.containsKey(component.getName()))
						compoNoInter.put(component.getName(),new ArrayList<String>());
					if (!compoNoInter.get(component.getName()).contains(intertop))
						compoNoInter.get(component.getName()).add(intertop);


					if (!getAttribut().contains("Req=!"+intertop))
						getAttribut().add("Req=!"+intertop);
				}
			}
		}


	}

	
	
	public Boolean isPair(String attribut, String component, int y) {
		//on parle le role de l'interface attribut required ou provided
		String strole = attribut.substring(0,attribut.indexOf("="));
		String strInterAtt = attribut.substring(attribut.indexOf('=')+1);
		ACLInterface aclInterAtt = cl.getInterfacesNames().get(strInterAtt);

		//si l'interface est provided
		if (strole.equals("Pro")){
			//on recupere la classification de cette interface
			ClInterfaceProvided clproAtt = getAbstractClassfication().getInterfacesProvided().get(aclInterAtt.getName());

			//pour toutes les interfaces contenues dans le composant
			ArrayList<ACLInterface> interEntity = getAbstractClassfication().getStructure().getComponentsProvided().get(component);

			for (ACLInterface aclInterEntity :interEntity){

				//on regarde si l'interface du comopsant est une interface enfant de l'interface attribut
				if (clproAtt.getLattice().isParent(aclInterAtt.toString(),aclInterEntity.toString()))
					return true;
			}
			return false;

		}
		else{
			if (strInterAtt.charAt(0) == '!'){
				//on enleve la negation
				strInterAtt = strInterAtt.substring(1);
				if (compoNoInter.containsKey(component)){
					if (compoNoInter.get(component).contains(strInterAtt)){
						getTable()[getAttribut().indexOf("Req="+strInterAtt)][y] = 1;

						//voir si il faut rajouter la possesion uniquement pour l'interface strInterAtt
						//ou pour toutes les interfaces appartenant a la classification de strInterAtt

						return true;
					}
				}
			}
			else{
				//on recupere la classification de cette interface
				ClInterfaceRequired clproAtt = getAbstractClassfication().getInterfacesRequired().get(aclInterAtt.getName());

				//pour toutes les interfaces contenues dans le composant
				ArrayList<ACLInterface> interEntity = getAbstractClassfication().getStructure().getComponentsRequired().get(component);
				for (ACLInterface aclInterEntity :interEntity){

					//on regarde si l'interface du comopsant est une interface enfant de l'interface attribut
					if (clproAtt.getLattice().isParent(aclInterAtt.toString(),aclInterEntity.toString()))
						return true;
				}
				return false;
			}
		}
		return false;
	}

	




	public String getType() {
		// TODO Auto-generated method stub
		return COMPONENT;
	}

	@Override
	public ACLEntity getACLEntity(String s) {
		System.out.println(s);
		return null;
	}

	




}
